package com.stetho.ai.b;

import android.util.Log;

import com.chaquo.python.PyObject;
import com.chaquo.python.Python;
import com.chaquo.python.android.AndroidPlatform;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;

/**
 * ai分析
 * create by duxl 2022/6/26
 */
public class AI {

    private final String TAG = "AI";
    private boolean isInit = false;
    private double samplingFrequency = 11025;
    private boolean removeFirstSecond = true;  // 默认删除前1秒钟的数据

    private AI() {
        if (!Python.isStarted()) {
            long start = System.currentTimeMillis();
            Log.i(TAG, "start AI...");
            Python.start(new AndroidPlatform(App.instance));
            Log.i(TAG, "start AI耗时=" + (System.currentTimeMillis() - start));
        }
    }

    public static AI getInstance() {
        return SingleHolder.INSTANCE;
    }

    private static class SingleHolder {
        private static AI INSTANCE = new AI();
    }

    /**
     * AI初始化（AI模块B没提供init方法）
     */
    public void init() {
        long start = System.currentTimeMillis();
        Log.i(TAG, "AI初始化...");
        if (!isInit) {
            Python py = Python.getInstance();
            // AI模块B没提供init方法
            //py.getModule().callAttr();
            isInit = true;
        }
        Log.i(TAG, "AI初始化耗时=" + (System.currentTimeMillis() - start));
    }


    /**
     * 通过pcm文件获取心率
     *
     * @param pcmFile
     * @return 返回心率
     */
    public float getBPM(String pcmFile) {
        long start = System.currentTimeMillis();
        Log.i(TAG, "根据心音文件获得心率BPM, pcmFile=" + pcmFile);
        float heartRate = 0;
        try {
            InputStream is = new FileInputStream(pcmFile);
            double[] audioData = processPcmFile(is);
            Python py = Python.getInstance();

            PyObject obj = py.getModule("getHeartRateSchmidt").callAttr("getHeartRateSchmidt", audioData, samplingFrequency);

            if (obj == null) {
                Log.e(TAG, "获取心率失败");
            } else {
                heartRate = obj.toFloat();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        Log.i(TAG, "根据心音文件获得心率BPM, heartRate=" + heartRate + ", 耗时=" + (System.currentTimeMillis() - start));
        return heartRate;
    }

    /**
     * 根据pcm文件判断是否是心音
     *
     * @param pcmFile
     * @return 返回true有效，返回false无效
     */
    public boolean checkHeartSoundValidity(String pcmFile) {
        long start = System.currentTimeMillis();
        Log.i(TAG, "根据pcm文件判断是否是心音, pcmFile=" + pcmFile);
        boolean isValid = false;
        try {
            InputStream is = new FileInputStream(pcmFile);
            double[] audioData = processPcmFile(is);
            Python py = Python.getInstance();

            double VALIDITY_THRESHOLD = 0.8;  // 默认的有效性阈值
            String mode = "relaxed"; // 可以改成 "strict" 测试严格模式
            //PyObject obj = py.getModule("check_heart_sound_validity").callAttr("check_heart_sound_validity", audioData, samplingFrequency, VALIDITY_THRESHOLD, mode);
            PyObject obj = py.getModule("check_heart_sound_validity").callAttr("check_heart_sound_validity", audioData, samplingFrequency, mode);

            if (obj == null) {
                Log.e(TAG, "根据pcm文件判断是否是心音失败");
            } else {
                isValid = obj.asList().get(0).toBoolean();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        Log.i(TAG, "根据pcm文件判断是否是心音, isValid=" + isValid + ", 耗时=" + (System.currentTimeMillis() - start));
        return isValid;
    }

    /**
     * 将心音数据换成AI需要的double数组类型
     *
     * @param pcmFileStream
     * @return
     * @throws IOException
     */
    private double[] processPcmFile(InputStream pcmFileStream) throws IOException {
        byte[] buffer = new byte[pcmFileStream.available()];
        pcmFileStream.read(buffer);
        pcmFileStream.close();

        double[] audioData = new double[buffer.length / 2];
        ByteBuffer byteBuffer = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN);
        for (int i = 0; i < audioData.length; i++) {
            audioData[i] = byteBuffer.getShort() / 32768.0;
        }

        // 删除前1秒钟的数据（如果启用）
        if (removeFirstSecond) {
            int samplesToRemove = (int) samplingFrequency;
            if (audioData.length > samplesToRemove) {
                audioData = Arrays.copyOfRange(audioData, samplesToRemove, audioData.length);
            }
        }

        return audioData;
    }
}
